//	ID: 066498650
//	Exercise #: 2
//	By:	Roy Moore
//
//	Written:	19/12/2011
//	Environment : VS2010
//
//-UDPTimeClient.cpp-

#include "UDPTimeClient.h"

void StartClient(SOCKET connSocket){
	string ip_addr;
	string serviceSelection;

	cout << "Please enter Server's IP address (0 = 127.0.0.1): ";
	cin >> ip_addr;
	if (ip_addr == "0") ip_addr = "127.0.0.1";

	sockaddr_in server_addr;
    server_addr.sin_family = AF_INET; 
	server_addr.sin_addr.s_addr = inet_addr(ip_addr.c_str());
	server_addr.sin_port = htons(TIME_PORT);

	MsgInfo clientMsgInfo;
	clientMsgInfo = InitMsgInfo();

	SelectService(connSocket, &clientMsgInfo, (sockaddr *) &server_addr);
}

void SelectService(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	char selectionChar;

	PrintServices();

	cin >> selectionChar;
	switch (selectionChar){
		case 'a':
			GetTime(connSocket, info, to_addr);
			break;
		case 'b':
			GetTimeWithoutYear(connSocket, info, to_addr);
			break;
		case 'c':
			GetTimeSinceEpoch(connSocket, info, to_addr);
			break;
		case 'd':
			GetClientToServerDelayEstimation(connSocket, info, to_addr);
			break;
		case 'e':
			MeasureRTT(connSocket, info, to_addr);
			break;
		case 'f':
			GetDayAndMounth(connSocket, info, to_addr);
			break;
		case 'g':
			GetYear(connSocket, info, to_addr);
			break;
		default :
			GetTime(connSocket, info, to_addr);
	}
}

void PrintServices(){
	cout << "Available Services:" << endl;
	for (int i = 0 ; i < NUMOFSERVICES ; i++){
		cout << serviceName[i] << endl;
	}
}

void GetTime(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	strncpy(info->sendBuff, serviceName[0].c_str(), BUFFER_SIZE); 
	//clientMsgInfo.sendBuff[strlen(clientMsgInfo.sendBuff)-1] = '\0'; //Need to end the string so we will know what size it is when sending
	GetTimeVar(connSocket, info, to_addr);
}

void GetTimeWithoutYear(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	strncpy(info->sendBuff, serviceName[1].c_str(), BUFFER_SIZE); 
	GetTimeVar(connSocket, info, to_addr);
}

void GetTimeSinceEpoch(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	strncpy(info->sendBuff, serviceName[2].c_str(), BUFFER_SIZE); 
	GetTimeVar(connSocket, info, to_addr);
}

void GetDayAndMounth(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	strncpy(info->sendBuff, serviceName[5].c_str(), BUFFER_SIZE); 
	GetTimeVar(connSocket, info, to_addr);
}

void GetYear(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	strncpy(info->sendBuff, serviceName[6].c_str(), BUFFER_SIZE); 
	GetTimeVar(connSocket, info, to_addr);
}

void GetTimeVar(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	SendDataTo(connSocket, info,(sockaddr *) to_addr);

	//cout<<"Time Client: Sent: " << info->bytesSent << "/" <<strlen(info->sendBuff) << " bytes of \"" <<info->sendBuff << "\" message." << endl;
	PrintStatus(Client, Send, info->bytesSent, info->sendBuff);

	RecvData(connSocket, info);

	//cout << "Time Client: Recieved: " << info->bytesRecv << " bytes of \"" << info->recvBuff << "\" message." << endl;
	PrintStatus(Client, Recive, info->bytesRecv, info->recvBuff);
}

void GetClientToServerDelayEstimation(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	string StrResponseArr[SAMPLECOUNT];
	long DataArr[SAMPLECOUNT];
	int sumOfdiff = 0, result;

	strncpy(info->sendBuff, serviceName[3].c_str(), BUFFER_SIZE); 

	for (int i = 0 ; i < SAMPLECOUNT ; i++){
		//cout << "Sending Msg #" << i + 1 << "/" << SAMPLECOUNT << endl;
		SendDataTo(connSocket, info,(sockaddr *) to_addr);
		PrintStatus(Client, Send, info->bytesSent, info->sendBuff);
	}

	cout << "->Finished sending " << SAMPLECOUNT << "Msgs" << endl;
	cout << "->Waiting For Replies..." << endl;

	for (int i = 0 ; i < SAMPLECOUNT ; i++){
		//cout << "Reciving Msg #" << i + 1 << "/" << SAMPLECOUNT << endl;
		RecvData(connSocket, info);
		PrintStatus(Client, Recive, info->bytesRecv, info->recvBuff);
		StrResponseArr[i] = info->recvBuff;
	}

	for (int i = 0 ; i < SAMPLECOUNT ; i++){
		DataArr[i] = atoi(StrResponseArr[i].c_str());
		//cout << "Converting String #" << i + 1 << "/" << SAMPLECOUNT << " with time: " << DataArr[i] << endl;
	}

	for (int i = 1 ; i < SAMPLECOUNT ; i++){
		sumOfdiff += (DataArr[i] - DataArr[i-1]);
	}

	result = sumOfdiff / (SAMPLECOUNT - 1);
	cout << endl << "->Average of the time signature is: " << result << "ms! " << "(" << SAMPLECOUNT << " Msgs)" << endl;
}

void MeasureRTT(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	long intSendTimeArr[SAMPLECOUNT];
	long intReciveTimeArr[SAMPLECOUNT];
	long DataArr[SAMPLECOUNT];
	int sumOfdiff = 0, result;

	strncpy(info->sendBuff, serviceName[4].c_str(), BUFFER_SIZE); 

	for (int i = 0 ; i < SAMPLECOUNT ; i++){
		SendDataTo(connSocket, info,(sockaddr *) to_addr);
		intSendTimeArr[i] = GetTickCount(); //Time from the moment the msg was sent
		PrintStatus(Client, Send, info->bytesSent, info->sendBuff);
		//cout << "(Sent Msg #" << i + 1 << "/" << SAMPLECOUNT << " with time: " << intSendTimeArr[i] << ")" << endl ;

		RecvData(connSocket, info);
		intReciveTimeArr[i] = GetTickCount(); //Time from the moment the msg recived
		PrintStatus(Client, Recive, info->bytesRecv, info->recvBuff);
		//cout << "(Recived Msg #" << i + 1 << "/" << SAMPLECOUNT << " with time: " << intReciveTimeArr[i] << ")" << endl ;
	}

	for (int i = 0 ; i < SAMPLECOUNT ; i++){
		
		DataArr[i] = (intReciveTimeArr[i] - intSendTimeArr[i]); // Time Recived - Time Sent = Timed needed
		//cout << intReciveTimeArr[i] << "-" << intSendTimeArr[i] << "=" << DataArr[i] << endl;
	}

	for (int i = 0 ; i < SAMPLECOUNT ; i++){
		sumOfdiff += DataArr[i];
	}

	result = sumOfdiff / (SAMPLECOUNT - 1);
	cout << endl << "->Average time From sent to recived: " << result << "ms !" << endl;
}